In [88]:
from array import array
import reprlib
import math
import numbers
import functools
import operator
import itertools
class Vector:
typecode = 'd'
def __init__(self, components):
self._components = array(self.typecode, components)
def __iter__(self):
return iter(self._components)
def __repr__(self):
components = reprlib.repr(self._components)
components = components[components.find('['):-1]
return 'Vector({})'.format(components)
def __str__(self):
return str(tuple(self))
def __bytes__(self):
return (bytes([ord(self.typecode)]) +
bytes(self._components))
def __eq__(self, other):
return (len(self) == len(other) and
all(a == b for a, b in zip(self, other)))
def __hash__(self):
hashes = (hash(x) for x in self._components)
return functools.reduce(operator.xor, hashes, 0)
def __abs__(self):
return math.sqrt(sum(x * x) for x in self)
def __bool__(self):
return bool(abs(self))
def __len__(self):
return len(self._components)
def __getitem__(self, index):
cls = type(self)
if isinstance(index, slice):
return cls(self._components[index])
elif isinstance(index, numbers.Integral):
return self._components[index]
else:
msg = '{.__name__} indices must be integers'
raise TypeError(msg.format(cls))
shortcut_names = 'xyzt'
def __getattr__(self, name):
cls = type(self)
if len(name) == 1:
pos = cls.shortcut_names.find(name)
if 0 <= pos < len(self._components):
return self._components[pos]
msg = '{.__name__!r} object has no atttribute {!r}'
raise AttributeError(msg.format(cls, name))
def __setattr__(self, name, value):
cls = type(self)
if len(name) == 1:
if name in cls.shortcut_names:
error = 'readonly attribute {attr_name!r}'
elif name.islower():
error = "can't set attributes 'a' to 'z' in {cls_name!r}"
else:
error = ''
if error:
msg = error.format(cls_name=cls.__name__, attr_name=name)
raise AttributeError(msg)
super().__setattr__(name, value)
def angle(self, n):
r = math.sqrt(sum(x * x for x in self[n:]))
a = math.atan2(r, self[n-1])
if (n == len(self) - 1) and (self[-1] < 0):
return math.pi * 2 - a
else:
return a
def angles(self):
return (self.angle(n) for n in range(1, len(self)))
def __format__(self, fmt_spec=''):
if fmt_spec.endswith('h'): # hyperspherical coordinates
fmt_spec = fmt_spec[:-1]
coords = itertools.chain([abs(self)], self.angles())
outer_fmt = '<{}>'
else:
coords = self
outer_fmt = '({})'
components = (format(c, fmt_spec) for c in coords)
return outer_fmt.format(', '.join(components))
@classmethod
def frombytes(cls, octets):
typecode = chr(octets[0])
memv = memoryview(octets[1:]).cast(typecode)
return cls(memv)
In [2]:
Vector([3.1, 4.2])
Out[2]:
In [3]:
Vector((3, 4, 5))
Out[3]:
In [4]:
Vector(range(10))
Out[4]:
In [8]:
v1 = Vector([3, 4, 5])
In [9]:
len(v1)
Out[9]:
In [10]:
v1[0], v1[-1]
Out[10]:
In [11]:
v7 = Vector(range(7))
v7[1:4]
Out[11]:
In [12]:
class MySeq:
def __getitem__(self, index):
return index
In [13]:
s = MySeq()
s[1]
Out[13]:
In [14]:
s[1:4]
Out[14]:
In [16]:
s[1:4:2]
Out[16]:
In [17]:
s[1:4:2, 9]
Out[17]:
In [18]:
s[1:4:2, 7:9]
Out[18]:
In [19]:
slice
Out[19]:
In [21]:
print(dir(slice))
In [22]:
help(slice.indices)
In [23]:
slice(None, 10, 2).indices(5)
Out[23]:
In [24]:
slice(-3, None, None).indices(5)
Out[24]:
In [39]:
v7 = Vector(range(7))
In [40]:
v7[-1]
Out[40]:
In [41]:
v7[1:4]
Out[41]:
In [42]:
v7[-1:]
Out[42]:
In [43]:
v7[1,2]
In [45]:
v = Vector(range(10))
v.x
Out[45]:
In [46]:
v.y, v.z, v.t
Out[46]:
In [69]:
v = Vector([0.0, 1.0, 2.0, 3.0, 4.0])
v.x
Out[69]:
In [71]:
v.x = 10
In [65]:
v
Out[65]:
In [72]:
2 * 3 * 4 * 5
Out[72]:
In [73]:
import functools
In [75]:
functools.reduce(lambda a,b: a*b, range(1,6))
Out[75]:
In [76]:
n = 0
for i in range(1, 6):
n ^= i
In [77]:
n
Out[77]:
In [78]:
functools.reduce(lambda a, b: a^b, range(6))
Out[78]:
In [79]:
import operator
In [80]:
functools.reduce(operator.xor, range(6))
Out[80]:
In [95]:
v = Vector((float(x) for x in range(1,10)))
In [96]:
v
Out[96]:
In [97]:
format(v,'h')
In [ ]: